home *** CD-ROM | disk | FTP | other *** search
- /*
- * Software shaders.
- * These operate in the mg environment.
- */
- #include "mgP.h"
-
- #define DOT(a,b) ((a).x*(b).x + (a).y*(b).y + (a).z*(b).z)
-
- #define CCMUL(A,B,C) ((C).r=(A).r*(B).r, (C).g=(A).g*(B).g, (C).b=(A).b*(B).b)
- #define CCADD(A,B,C) ((C).r=(A).r+(B).r, (C).g=(A).g+(B).g, (C).b=(A).b+(B).b, (C).a = (A).a + (B).a)
-
- #define CSCALE(s, A, B) ( (B).r = (A).r * s, (B).g = (A).g * s, (B).b = (A).b * s, (B).a = (A).b * s)
-
-
- #define CCSADD(A,B,s,C) \
- ((C).r += (s)*(A).r*(B).r, \
- (C).g += (s)*(A).g*(B).g, \
- (C).b += (s)*(A).b*(B).b)
-
- /*
- * Transform a vector covariantly
- */
- static void
- cotransform(register Transform Tinv, register Point3 *in, Point3 *out)
- {
- out->x = Tinv[0][0]*in->x + Tinv[0][1]*in->y + Tinv[0][2]*in->z;
- out->y = Tinv[1][0]*in->x + Tinv[1][1]*in->y + Tinv[1][2]*in->z;
- out->z = Tinv[2][0]*in->x + Tinv[2][1]*in->y + Tinv[2][2]*in->z;
- }
-
- static float euck1 = 1.0; /* inverse power falloff */
- static float euck2 = 0.0; /* safety zone around light */
- static float fog = 0.0; /* fog control */
- static float hypk1 = .5; /* controls exponential falloff */
- static float hypk2 = .0; /* controls exponential falloff */
- static float sphk1 = .5; /* controls exponential falloff */
- static float sphk2 = 0.0; /* safety zone around light */
-
- /*
- * Euclidean shader
- *
- * We depend on the following mg features:
- * _mgc->xstk->hasinv (cleared whenever transform changes)
- * _mgc->W2C, C2W (initialized from camera at mgworldbegin())
- */
-
- int mg_eucshade(int nv, HPoint3 *v, Point3 *n, ColorA *c, ColorA *cs)
- {
- struct mgxstk *mx = _mgc->xstk;
- struct mgastk *ma = _mgc->astk;
- struct LtLight *l;
- int i;
- HPoint3 V;
- Point3 N, I;
- float s;
- Color Ca;
-
- euck1 = ma->lighting.attenmult;
- euck2 = ma->lighting.attenmult2;
- fog = ma->lighting.attenconst;
- #define EYE ((HPoint3 *) (_mgc->C2W[3])) /* Eye (camera) position as an HPoint3 */
-
- if(!mx->hasinv) {
- TmInvert(mx->T, mx->Tinv);
- mx->hasinv = 1;
- }
-
- /* "ambient" color */
-
- Ca.r = Ca.g = Ca.b = 0;
- CCSADD(ma->mat.ambient, ma->lighting.ambient, ma->mat.ka, Ca);
-
- for(i = 0; i < nv; i++, v++, n++, c++, cs++) {
- ColorA *thiscolor = c;
-
- /* Transform point by T */
- HPt3Transform(mx->T, v, &V); /* V = v in world coords */
- HPt3SubPt3(EYE, &V, &I); /* I = EYE - V (point-to-eye vector) */
-
- /* Transform normal by T'^-1 */
- cotransform(mx->Tinv, n, &N);
- s = 1/sqrt(DOT(N,N));
- if(DOT(N,I) < 0) {
- s = -s; /* Flip normal to face the viewer */
-
- /* Hack: use otherwise-useless emission color, if defined,
- * as the back-side material color.
- */
- if(ma->mat.valid & MTF_EMISSION)
- thiscolor = (ColorA*)&ma->mat.emission;
- }
-
- N.x *= s; N.y *= s; N.z *= s;
-
- /* Ambient term */
- *(Color *)cs = Ca;
-
- for(l = ma->lighting.lights; l != NULL; l = l->next) {
- register Point3 *L;
- Point3 Lt;
- float bright, ls, ll, ln, power;
-
- /* Diffuse term */
- bright = l->intensity;
- if(l->globalposition.w == 0) {
- L = (Point3 *)&l->globalposition;
- ll = DOT(*L,*L);
- } else {
- HPt3SubPt3(&l->globalposition, &V, &Lt);
- L = ≪
- ll = DOT(Lt,Lt);
- /* ll = (ll > euck2) ? ll : euck2; */
- power = pow(ll, -euck1/2.0);
- /* Inverse square falloff */
- bright *= power;
- }
-
- ln = DOT(*L,N);
- if(ln <= 0) /* Ignore lights shining from behind */
- continue;
-
- ls = sqrt(ll);
- s = ma->mat.kd * bright * (ln/ls);
- /* cosine law: L.N diffuse shading */
-
- CCSADD(l->color, *thiscolor, s, *cs);
-
- if(ma->mat.ks > 0) { /* Specular term */
- Point3 H; /* H: halfway between L and I */
-
- H.x = L->x/ls + I.x, H.y = L->y/ls + I.y, H.z = L->z/ls + I.z;
-
- s = DOT(H,N) / sqrt(DOT(H,H));
- /* cos angle(H,N) */
-
- /* Note we need s>=0 for specular term to make sense.
- * This should be true since we checked
- * that both L.N and I.N are positive above.
- */
-
- /* shininess = specular exponent */
- s = ma->mat.ks * bright * pow(s, ma->mat.shininess);
-
- CCSADD(l->color, ma->mat.specular, s, *cs);
- }
- }
- /* insert fog code */
- if (fog) {
- float k1, k2;
- float d = HPt3Distance(&V, EYE);
- ColorA surfcolor, fogcolor;
- d = d - euck2; /* fog-free sphere of radius euck2 */
- if (d < 0) d = 0;
- k1 = exp( -fog * d);
- k2 = 1.0 - k1;
- CSCALE(k1, *cs, surfcolor);
- CSCALE(k2, _mgc->background, fogcolor);
- CCADD(surfcolor, fogcolor, *cs);
- }
-
- if(cs->r < 0) cs->r = 0; else if(cs->r > 1) cs->r = 1;
- if(cs->g < 0) cs->g = 0; else if(cs->g > 1) cs->g = 1;
- if(cs->b < 0) cs->b = 0; else if(cs->b > 1) cs->b = 1;
- cs->a = c->a;
- }
- return 0;
- }
-